package nl.rainbowsheep.reisorg.rest.service.model;

import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.Column;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.MapKeyJoinColumn;
import javax.persistence.PostLoad;
import javax.persistence.PostUpdate;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import nl.rainbowsheep.reisorg.rest.service.util.Localizer;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.springframework.format.annotation.DateTimeFormat;

@Entity
@Table(name = "accommodation_housings")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class AccommodationHousing implements Serializable, ILocalized {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "accommodation_housing_id")
    private long id;

    @Column(name = "fake_description")
    private String description;

    @Column(name = "last_update")
    @DateTimeFormat(pattern = "dd-MM-yyyy HH:mm:SS")
    @Temporal(javax.persistence.TemporalType.DATE)
    private Date lastUpdate;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "accommodation_housings_locale", joinColumns = @JoinColumn(name = "accommodation_housings_fk"))
    @MapKeyJoinColumn(name = "languages_fk")
    private Map<Language, AccommodationHousingLocalized> locale;

    @Column(name = "accommodation_fk")
    private long accommodationId;

    @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @JoinTable(name = "accommodation_housing_prices",
            joinColumns = {
                @JoinColumn(name = "accommodation_housings_fk")},
            inverseJoinColumns = {
                @JoinColumn(name = "prices_fk")})
    private List<Price> prices;

    @Column(name = "title")
    @NotNull
    private String title;

    @Column(name = "min_persons")
    @NotNull
    private int minPersons;

    @Column(name = "max_persons")
    @NotNull
    private int maxPersons;
    
    @Transient
    private Price currentPrice;

    public List<Price> getPrices() {
        return prices;
    }

    @JsonIgnore
    public void setPrices(List<Price> prices) {
        this.prices = prices;
    }

    public Price getCurrentPrice() {

        for (Price price : this.prices) {
            if (this.currentPrice != null) {
                if (price.getStartDate().after(this.currentPrice.getStartDate()) && price.isIsActive()) {
                    this.currentPrice = price;
                }
            } else {
                this.currentPrice = price;
            }
        }
        return this.currentPrice;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public long getAccommodationId() {
        return accommodationId;
    }

    public void setAccommodationId(long accommodationId) {
        this.accommodationId = accommodationId;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public int getMinPersons() {
        return minPersons;
    }

    public void setMinPersons(int minPersons) {
        this.minPersons = minPersons;
    }

    public int getMaxPersons() {
        return maxPersons;
    }

    public void setMaxPersons(int maxPersons) {
        this.maxPersons = maxPersons;
    }

    @JsonIgnore
    @Override
    public Map getLocale() {
        return locale;
    }

    @Override
    public void setLocale(Map locale) {
        this.locale = locale;
    }

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {

        this.description = description;
    }

    public Date getLastUpdate() {
        return lastUpdate;
    }

    public void setLastUpdate(Date lastUpdate) {
        this.lastUpdate = lastUpdate;
    }

    @Override
    @PostLoad
    @PostUpdate
    public void localize() {
        AccommodationHousingLocalized localizedObject
                = (AccommodationHousingLocalized) Localizer.getLocalizedObject(this.locale, AccommodationHousingLocalized.class);
        this.description = localizedObject.getDescription();
    }

    @Override
    @PreUpdate
    @PrePersist
    public void parseLocalizedData() {
        AccommodationHousingLocalized localizedObject = null;
        if (this.locale == null) {
            this.locale = new HashMap<Language, AccommodationHousingLocalized>();
        }
        if (Localizer.getLocalizedObject(this.locale, AccommodationHousingLocalized.class) != null) {
            localizedObject
                    = (AccommodationHousingLocalized) Localizer.getLocalizedObject(this.locale, AccommodationHousingLocalized.class);
        } else {
            localizedObject = new AccommodationHousingLocalized();
            this.locale.put(Localizer.getCurrentLanguage(), localizedObject);
        }
        localizedObject.setDescription(this.description);
    }
}
